﻿
#region 程序集引用区
using System;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using SubSonic.DataProviders;
using SubSonic.Extensions;
using SubSonic.Linq.Structure;
using SubSonic.Query;
using SubSonic.Schema;
using System.Data.Common;
using System.Collections.Generic;
#endregion

namespace eTerm.MsSql.DbProvider{
    
    /// <summary>
    /// 文 件 名: SqlDbProvider.cs
    /// CLR版本 : v2.0.50727
    /// 作   者 : lijun.hu
    /// 版    权: Copyright @2011 lijun.hu(FORCEN HU) 
    /// 电子邮箱：lijun.hu@shinsoft.net
    /// 说    明: Sql Server 数据库访问体
    /// 生成日期: 2013年8月2日
    /// </summary>
    public partial class SqlDbProvider : IQuerySurface{
        
        #region 变量定义
        public IDataProvider DataProvider;
        public DbQueryProvider provider;
        
        public static IDataProvider DefaultDataProvider { get; set; }
        #endregion
        
        #region 构造函数
        public SqlDbProvider() 
        {
            if (DefaultDataProvider == null) {
                DataProvider = ProviderFactory.GetProvider("Sql");
            }
            else {
                DataProvider = DefaultDataProvider;
            }
            Init();
        }

        public SqlDbProvider(string connectionStringName)
        {
            DataProvider = ProviderFactory.GetProvider(connectionStringName);
            Init();
        }
        
        public SqlDbProvider(string connectionString, string providerName)
        {
            DataProvider = ProviderFactory.GetProvider(connectionString,providerName);
            Init();
        }
        #endregion
        
        #region IQuerySurface实现部份
        public ITable FindByPrimaryKey(string pkName)
        {
            return DataProvider.Schema.Tables.SingleOrDefault(x => x.PrimaryKey.Name.Equals(pkName, StringComparison.InvariantCultureIgnoreCase));
        }

        public Query<T> GetQuery<T>()
        {
            return new Query<T>(provider);
        }
        
        public ITable FindTable(string tableName)
        {
            return DataProvider.FindTable(tableName);
        }
               
        public IDataProvider Provider
        {
            get { return DataProvider; }
            set {DataProvider=value;}
        }
        
        public DbQueryProvider QueryProvider
        {
            get { return provider; }
        }
        
        BatchQuery _batch = null;
        public void Queue<T>(IQueryable<T> qry)
        {
            if (_batch == null)
                _batch = new BatchQuery(Provider, QueryProvider);
            _batch.Queue(qry);
        }

        public void Queue(ISqlQuery qry)
        {
            if (_batch == null)
                _batch = new BatchQuery(Provider, QueryProvider);
            _batch.Queue(qry);
        }

        public void ExecuteTransaction(IList<DbCommand> commands)
		{
            //if(!TestMode)
			{
                using(var connection = commands[0].Connection)
				{
                   if (connection.State == ConnectionState.Closed)
                        connection.Open();
                   
                   using (var trans = connection.BeginTransaction()) 
				   {
                        foreach (var cmd in commands) 
						{
                            cmd.Transaction = trans;
                            cmd.Connection = connection;
                            cmd.ExecuteNonQuery();
                        }
                        trans.Commit();
                    }
                    connection.Close();
                }
            }
        }

        public IDataReader ExecuteBatch()
        {
            if (_batch == null)
                throw new InvalidOperationException("There's nothing in the queue");
            //if(!TestMode)
            return _batch.ExecuteReader();
        }
        #endregion
        
        #region 查询
        /// <summary>
        /// “未定义” 查询提供者.
        /// </summary>
        public Query< PnrCabin > PnrCabins { get; set; }
        /// <summary>
        /// “未定义” 查询提供者.
        /// </summary>
        public Query< PnrDetr > PnrDetrs { get; set; }
        /// <summary>
        /// “票号处理历史” 查询提供者.
        /// </summary>
        public Query< PnrHistory > PnrHistorys { get; set; }
        /// <summary>
        /// “未定义” 查询提供者.
        /// </summary>
        public Query< PnrPassenger > PnrPassengers { get; set; }
        /// <summary>
        /// “占座PNR库” 查询提供者.
        /// </summary>
        public Query< PnrRequire > PnrRequires { get; set; }
        /// <summary>
        /// “未定义” 查询提供者.
        /// </summary>
        public Query< PnrRequireCode > PnrRequireCodes { get; set; }
        /// <summary>
        /// “未定义” 查询提供者.
        /// </summary>
        public Query< PnrSegment > PnrSegments { get; set; }
        /// <summary>
        /// “未定义” 查询提供者.
        /// </summary>
        public Query< PnrSentHistory > PnrSentHistorys { get; set; }
        /// <summary>
        /// “未定义” 查询提供者.
        /// </summary>
        public Query< SetupBin > SetupBins { get; set; }
        /// <summary>
        /// “页面权限表” 查询提供者.
        /// </summary>
        public Query< SysAuthority > SysAuthoritys { get; set; }
        /// <summary>
        /// “未定义” 查询提供者.
        /// </summary>
        public Query< SysCompany > SysCompanys { get; set; }
        /// <summary>
        /// “系统日志表” 查询提供者.
        /// </summary>
        public Query< SysDbLog > SysDbLogs { get; set; }
        /// <summary>
        /// “未定义” 查询提供者.
        /// </summary>
        public Query< SysMail > SysMails { get; set; }
        /// <summary>
        /// “用户表” 查询提供者.
        /// </summary>
        public Query< SysUser > SysUsers { get; set; }
        /// <summary>
        /// “用户权限关联表” 查询提供者.
        /// </summary>
        public Query< SysUserAuthority > SysUserAuthoritys { get; set; }
        #endregion
        
        #region ' Aggregates and SubSonic Queries '
        public Select SelectColumns(params string[] columns)
        {
            return new Select(DataProvider, columns);
        }

        public Select Select
        {
            get { return new Select(this.Provider); }
        }

        public Insert Insert
		{
            get { return new Insert(this.Provider); }
        }

        public Update<T> Update<T>() where T:new()
		{
            return new Update<T>(this.Provider);
        }

        public SqlQuery Delete<T>(Expression<Func<T,bool>> column) where T:new()
        {
            LambdaExpression lamda = column;
            SqlQuery result = new Delete<T>(this.Provider);
            result = result.From<T>();
            result.Constraints=lamda.ParseConstraints().ToList();
            return result;
        }

        public SqlQuery Max<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = DataProvider.FindTable(objectName).Name;
            return new Select(DataProvider, new Aggregate(colName, AggregateFunction.Max)).From(tableName);
        }

        public SqlQuery Min<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = this.Provider.FindTable(objectName).Name;
            return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Min)).From(tableName);
        }

        public SqlQuery Sum<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = this.Provider.FindTable(objectName).Name;
            return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Sum)).From(tableName);
        }

        public SqlQuery Avg<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = this.Provider.FindTable(objectName).Name;
            return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Avg)).From(tableName);
        }

        public SqlQuery Count<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = this.Provider.FindTable(objectName).Name;
            return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Count)).From(tableName);
        }

        public SqlQuery Variance<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = this.Provider.FindTable(objectName).Name;
            return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Var)).From(tableName);
        }

        public SqlQuery StandardDeviation<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = this.Provider.FindTable(objectName).Name;
            return new Select(this.Provider, new Aggregate(colName, AggregateFunction.StDev)).From(tableName);
        }
        #endregion
        
        #region 构造初始化
        void Init()
        {
            provider = new DbQueryProvider(this.Provider);

            #region ' Query Defs '
            PnrCabins = new Query< PnrCabin >(provider);
            PnrDetrs = new Query< PnrDetr >(provider);
            PnrHistorys = new Query< PnrHistory >(provider);
            PnrPassengers = new Query< PnrPassenger >(provider);
            PnrRequires = new Query< PnrRequire >(provider);
            PnrRequireCodes = new Query< PnrRequireCode >(provider);
            PnrSegments = new Query< PnrSegment >(provider);
            PnrSentHistorys = new Query< PnrSentHistory >(provider);
            SetupBins = new Query< SetupBin >(provider);
            SysAuthoritys = new Query< SysAuthority >(provider);
            SysCompanys = new Query< SysCompany >(provider);
            SysDbLogs = new Query< SysDbLog >(provider);
            SysMails = new Query< SysMail >(provider);
            SysUsers = new Query< SysUser >(provider);
            SysUserAuthoritys = new Query< SysUserAuthority >(provider);
            #endregion

            #region ' Schemas '
        	if(DataProvider.Schema.Tables.Count == 0)
			{
            	DataProvider.Schema.Tables.Add(new PNR_CabinTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new PNR_DetrTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new PNR_HistoryTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new PNR_PassengerTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new PNR_RequireTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new PNR_RequireCodeTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new PNR_SegmentTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new PNR_SentHistoryTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new SetupBinTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new Sys_AuthorityTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new Sys_CompanyTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new Sys_DbLogTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new Sys_MailTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new Sys_UserTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new Sys_UserAuthorityTable(DataProvider));
            }
            #endregion
        }
        #endregion
    }
}